package com.docx4j.util;


import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageSize;
import org.docx4j.UnitsOfMeasurement;
import org.docx4j.dml.wordprocessingDrawing.Anchor;
import org.docx4j.model.structure.PageDimensions;
import org.docx4j.model.structure.SectionWrapper;
import org.docx4j.openpackaging.contenttype.ContentTypeManager;
import org.docx4j.openpackaging.exceptions.InvalidFormatException;
import org.docx4j.openpackaging.packages.OpcPackage;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.ExternalTarget;
import org.docx4j.openpackaging.parts.Part;
import org.docx4j.openpackaging.parts.PartName;
import org.docx4j.openpackaging.parts.WordprocessingML.ImagePngPart;
import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
import org.docx4j.relationships.Relationship;

import javax.xml.bind.JAXBElement;
import java.awt.geom.Dimension2D;
import java.io.File;
import java.io.FileInputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

public class MyBinaryPartAbstractImage extends ImagePngPart {

    final static String namespaces = " xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" "
            + "xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" "
            + "xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\"";
    private static ImageInfo imageInfo;

    private static List<Relationship> rels = new ArrayList<Relationship>();

    public Relationship getRelLast() {
        int size = rels.size();
        System.out.println("getRelLast size " + size);
        if (size < 1) {
            return null;
        } else {
            return rels.get(size - 1);
        }
    }


    public MyBinaryPartAbstractImage(PartName partName) throws InvalidFormatException {
        super(partName);
    }

    public MyBinaryPartAbstractImage(ExternalTarget externalTarget) {
        super(externalTarget);
    }

    public static MyBinaryPartAbstractImage createImagePart(OpcPackage opcPackage, Part sourcePart, File imageFile) throws Exception {
        byte[] locByte = new byte[1];
        imageInfo = getImageInfo(new URL("file:/" + imageFile.getAbsolutePath()));
        ContentTypeManager ctm = opcPackage.getContentTypeManager();
        if (sourcePart.getRelationshipsPart() == null) {
            RelationshipsPart.createRelationshipsPartForPart(sourcePart);
        }

        String proposedRelId = sourcePart.getRelationshipsPart().getNextId();
        String ext = imageInfo.getMimeType().substring(imageInfo.getMimeType().indexOf("/") + 1);
        String partName = PartName.generateUniqueName(sourcePart, proposedRelId, "/word/media/", "image", ext);
        MyBinaryPartAbstractImage imagePart = new MyBinaryPartAbstractImage(new PartName(partName));
//        MyBinaryPartAbstractImage imagePart = (MyBinaryPartAbstractImage) ctm.newPartForContentType(imageInfo.getMimeType(), createImageName(opcPackage, sourcePart, proposedRelId, ext), (Relationship) null);
//        log.debug("created part " + imagePart.getClass().getName() + " with name " + imagePart.getPartName().toString());
        System.out.println("created part " + imagePart.getClass().getName() + " with name " + imagePart.getPartName().toString());

        FileInputStream fis = new FileInputStream(imageFile);
        imagePart.setBinaryData(fis);
//        rels.add(sourcePart.addTargetPart(imagePart, proposedRelId));
        imagePart.rels.add(sourcePart.addTargetPart(imagePart, proposedRelId));
        imagePart.setImageInfo(imageInfo);
        return imagePart;
    }

    /**
     * Create a <wp:inline> element suitable for this image,
     * which can be linked or embedded in w:p/w:r/w:drawing.
     * If the image is wider than the page, it will be scaled
     * automatically.
     *
     * @param filenameHint Any text, for example the original filename
     * @param altText      Like HTML's alt text
     * @param id1          An id unique in the document
     * @param id2          Another id unique in the document
     *                     None of these things seem to be exposed in Word 2007's
     *                     user interface, but Word won't open the document if
     *                     any of the attributes these go in (except @ desc) aren't present!
     * @throws Exception
     */
    public Anchor createImageAnchor(WordprocessingMLPackage wordMLPackage, String filenameHint, String altText,
                                    int id1, int id2, long cx, long cy, long posHOffset, long posVOffset) throws Exception {

//        WordprocessingMLPackage wmlPackage = ((WordprocessingMLPackage) this.getPackage());

        List<SectionWrapper> sections = wordMLPackage.getDocumentModel().getSections();
        PageDimensions page = sections.get(sections.size() - 1).getPageDimensions();

        CxCy cxcy = CxCy.scale(imageInfo, page);

//        return createImageAnchor(filenameHint, altText, id1, id2, cxcy.getCx(), cxcy.getCy(), link, posHOffset, posVOffset);
        return createImageAnchor(filenameHint, altText, id1, id2, cx, cy, posHOffset, posVOffset);
    }


    /**
     * Create a <wp:inline> element suitable for this image,
     * which can be _embedded_ in w:p/w:r/w:drawing.
     *
     * @param filenameHint Any text, for example the original filename
     * @param altText      Like HTML's alt text
     * @param id1          An id unique in the document
     * @param id2          Another id unique in the document
     * @param cx           Image width in twip
     *                     None of these things seem to be exposed in Word 2007's
     *                     user interface, but Word won't open the document if
     *                     any of the attributes these go in (except @ desc) aren't present!
     * @throws Exception
     */
    public Anchor createImageAnchor(String filenameHint, String altText, int id1, int id2, long cx, long cy, long posHOffset, long posVOffset) throws Exception {

        ImageSize size = imageInfo.getSize();

        Dimension2D dPt = size.getDimensionPt();
        double imageWidthTwips = dPt.getWidth() * 20;
//        log.debug("imageWidthTwips: " + imageWidthTwips);
        System.out.println("imageWidthTwips: " + imageWidthTwips);

//        log.debug("Scaling image height to retain aspect ratio");
        System.out.println("Scaling image height to retain aspect ratio");

//        cy = UnitsOfMeasurement.twipToEMU(dPt.getHeight() * 20 * cx / imageWidthTwips);

        // Now convert cx to EMU
        cx = UnitsOfMeasurement.twipToEMU(cx);
        cy = UnitsOfMeasurement.twipToEMU(cy);


//        log.debug("cx=" + cx + "; cy=" + cy);
        System.out.println("cx=" + cx + "; cy=" + cy);

        return createImageAnchor(filenameHint, altText, id1, id2, cx, cy, posHOffset, posVOffset, false);
    }

    /**
     * Create a <wp:anchor> element suitable for this image, which can be
     * linked or embedded in w:p/w:r/w:drawing, specifying height and width.  Note
     * that you'd ordinarily use one of the methods which don't require
     * you to specify height (cy).
     *
     * @param filenameHint Any text, for example the original filename
     * @param altText      Like HTML's alt text
     * @param id1          An id unique in the document
     * @param id2          Another id unique in the document None of these things seem to
     *                     be exposed in Word 2007's user interface, but Word won't open
     *                     the document if any of the attributes these go in (except @ desc) aren't
     *                     present!
     * @param cx           Image width in EMU
     * @param cy           Image height in EMU
     * @param link         true if this is to be linked not embedded
     * @throws Exception
     */
    public Anchor createImageAnchor(String filenameHint, String altText,
                                    int id1, int id2, long cx, long cy, long posHOffset, long posVOffset, boolean link
    ) throws Exception {

        // Floating - The drawing object is anchored within the text, but can be absolutely positioned in the
        // document relative to the page.

        if (filenameHint == null) {
            filenameHint = "";
        }
        if (altText == null) {
            altText = "";
        }

        String type;
        if (link) {
            type = "r:link";
        } else {
            type = "r:embed";
        }

        String ml = "<wp:anchor distT=\"0\" distB=\"0\" distL=\"114300\" distR=\"114300\" simplePos=\"0\" relativeHeight=\"251658240\" behindDoc=\"0\" locked=\"0\" layoutInCell=\"1\" allowOverlap=\"1\"" + namespaces + ">" //  wp14:anchorId=\"28C768E3\" wp14:editId=\"050FA02A\">"
                + "<wp:simplePos x=\"1\" y=\"1\"/>"
                + "<wp:positionH relativeFrom=\"column\"><wp:posOffset>${posHOffset}</wp:posOffset></wp:positionH>"
                + "<wp:positionV relativeFrom=\"paragraph\"><wp:posOffset>${posVOffset}</wp:posOffset></wp:positionV>"
                + "<wp:extent cx=\"${cx}\" cy=\"${cy}\"/>"
                + "<wp:effectExtent l=\"0\" t=\"0\" r=\"0\" b=\"0\"/>"  // b=4445
                + "<wp:wrapNone/>"
                + "<wp:docPr id=\"${id1}\" name=\"${filenameHint}\" descr=\"${altText}\"/><wp:cNvGraphicFramePr><a:graphicFrameLocks xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\" noChangeAspect=\"1\"/></wp:cNvGraphicFramePr>"
                + "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">"
                + " <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"
                + " <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\"><pic:nvPicPr><pic:cNvPr id=\"${id2}\" name=\"${filenameHint}\"/><pic:cNvPicPr/></pic:nvPicPr>"
                + "<pic:blipFill><a:blip " + type + "=\"${rEmbedId}\">"
//		           + " <a:extLst><a:ext uri=\"{28A0092B-C50C-407E-A947-70E740481C1C}\"><a14:useLocalDpi xmlns:a14=\"http://schemas.microsoft.com/office/drawing/2010/main\" val=\"0\"/></a:ext></a:extLst>"
                + "</a:blip><a:stretch><a:fillRect/></a:stretch></pic:blipFill>"
                + "<pic:spPr><a:xfrm><a:off x=\"0\" y=\"0\"/><a:ext cx=\"${cx}\" cy=\"${cy}\"/></a:xfrm><a:prstGeom prst=\"rect\"><a:avLst/></a:prstGeom></pic:spPr></pic:pic></a:graphicData>"
                + "</a:graphic>"
//		      + "<wp14:sizeRelH relativeFrom=\"page\"><wp14:pctWidth>0</wp14:pctWidth></wp14:sizeRelH><wp14:sizeRelV relativeFrom=\"page\"><wp14:pctHeight>0</wp14:pctHeight></wp14:sizeRelV>"
                + "</wp:anchor>";


        java.util.HashMap<String, String> mappings = new java.util.HashMap<String, String>();

        mappings.put("cx", Long.toString(cx));
        mappings.put("cy", Long.toString(cy));
        mappings.put("filenameHint", filenameHint);
        mappings.put("altText", altText);
        mappings.put("rEmbedId", getRelLast().getId());
        mappings.put("id1", Integer.toString(id1));
        mappings.put("id2", Integer.toString(id2));
        mappings.put("posHOffset", Long.toString(posHOffset));
        mappings.put("posVOffset", Long.toString(posVOffset));

        System.out.println("............................. createImageAnchor.xml : " + ml);
        System.out.println("............................. createImageAnchor.mappings : " + mappings);

        Object o = org.docx4j.XmlUtils.unmarshallFromTemplate(ml, mappings);

        Anchor anchor = (Anchor) ((JAXBElement) o).getValue();

        return anchor;
    }


}//class

